﻿using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Niaofei.Application.Services
{
    public class CaptchaGenerator
    {
        private const int Width = 200;
        private const int Height = 80;
        private const int FontSize = 30;
        private const string Characters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
        private const int NoisePointCount = 100;
        private const int NoiseLineCount = 5;

        private static readonly Color[] BackgroundColors =
        {
            Color.LightGray, Color.LightBlue, Color.LightPink, Color.LightGreen
        };

        private static readonly Color[] TextColors =
        {
            Color.DarkBlue, Color.DarkRed, Color.DarkGreen, Color.Black
        };

        private readonly Font[] _fonts;

        public CaptchaGenerator()
        {
            // 初始化字体集合（兼容2.1.3版本）
            var fontCollection = new FontCollection();

            // 尝试加载常见字体
            _fonts = new FontFamily?[]
            {
                SystemFonts.TryGet("Arial", out var arial) ? arial : null,
                SystemFonts.TryGet("Times New Roman", out var times) ? times : null,
                SystemFonts.TryGet("Courier New", out var courier) ? courier : null,
                SystemFonts.TryGet("Verdana", out var verdana) ? verdana : null
            }
            .Where(f => f != null)
            .Select(f => new Font(f!.Value, FontSize))
            .ToArray();

            // 如果系统没有预装字体，添加默认字体
            if (_fonts.Length == 0)
            {
                var defaultFamily = fontCollection.AddSystemFonts().Families.First();
                _fonts = new[] { defaultFamily.CreateFont(FontSize) };
            }
        }

        public (string Code, byte[] ImageBytes) GenerateCaptcha()
        {
            // 生成随机验证码（4-6个字符）
            var codeLength = Random.Shared.Next(4, 7);
            var code = GenerateRandomCode(codeLength);

            // 创建空白图像
            using var image = new Image<Rgba32>(Width, Height);

            // 填充背景色
            var bgColor = BackgroundColors[Random.Shared.Next(BackgroundColors.Length)];
            image.Mutate(ctx => ctx.Fill(bgColor));

            // 绘制验证码文本
            DrawCaptchaText(image, code);

            // 添加干扰元素
            AddNoise(image);

            // 扭曲文本
            DistortText(image);

            // 转换为字节数组
            using var ms = new MemoryStream();
            image.SaveAsPng(ms);
            return (code, ms.ToArray());
        }

        private string GenerateRandomCode(int length)
        {
            return new string(
                Enumerable.Repeat(Characters, length)
                          .Select(s => s[Random.Shared.Next(s.Length)])
                          .ToArray()
            );
        }

        private void DrawCaptchaText(Image<Rgba32> image, string code)
        {
            var startX = 20;
            var spacing = (Width - 40) / code.Length;

            image.Mutate(ctx =>
            {
                for (int i = 0; i < code.Length; i++)
                {
                    // 为每个字符选择随机字体、颜色和旋转角度
                    var font = _fonts[Random.Shared.Next(_fonts.Length)];
                    var color = TextColors[Random.Shared.Next(TextColors.Length)];
                    var rotation = Random.Shared.Next(-15, 15);

                    // 设置字符位置（增加随机偏移）
                    var position = new PointF(
                        startX + Random.Shared.Next(-3, 3),
                        Height / 2f + Random.Shared.Next(-10, 10)
                    );

                    // 创建文本选项
                    var textOptions = new TextOptions(font)
                    {
                        Origin = position,
                        HorizontalAlignment = HorizontalAlignment.Left,
                        VerticalAlignment = VerticalAlignment.Center,
                        TextAlignment = TextAlignment.Start,
                        WrappingLength = 0
                    };

                    // 绘制字符
                    ctx.DrawText(
                        code[i].ToString(),
                        font,
                        Brushes.Solid(color),
                        position
                    );

                    // 移动到下一个字符位置
                    startX += spacing;
                }
            });
        }

        private void AddNoise(Image<Rgba32> image)
        {
            image.Mutate(ctx =>
            {
                // 添加噪点
                for (int i = 0; i < NoisePointCount; i++)
                {
                    var color = TextColors[Random.Shared.Next(TextColors.Length)];
                    var point = new PointF(
                        Random.Shared.Next(0, Width),
                        Random.Shared.Next(0, Height)
                    );

                    ctx.Draw(
                        new SolidBrush(color),
                        1f, // 点大小
                        new ComplexPolygon(new EllipsePolygon(point, new SizeF(1, 1)))
                    );
                }

                // 添加干扰线
                for (int i = 0; i < NoiseLineCount; i++)
                {
                    var color = TextColors[Random.Shared.Next(TextColors.Length)];
                    var thickness = Random.Shared.Next(1, 3);

                    var points = new[]
                    {
                        new PointF(Random.Shared.Next(0, Width), Random.Shared.Next(0, Height)),
                        new PointF(Random.Shared.Next(0, Width), Random.Shared.Next(0, Height))
                    };

                    ctx.DrawLine(
                        new SolidPen(color, thickness),
                        points
                    );
                }

                // 添加干扰曲线
                for (int i = 0; i < NoiseLineCount / 2; i++)
                {
                    var color = TextColors[Random.Shared.Next(TextColors.Length)];
                    var thickness = Random.Shared.Next(1, 2);

                    var points = new List<PointF>();
                    var start = new PointF(Random.Shared.Next(0, Width), Random.Shared.Next(0, Height));
                    points.Add(start);

                    for (int j = 0; j < 3; j++)
                    {
                        points.Add(new PointF(
                            points.Last().X + Random.Shared.Next(10, 50),
                            points.Last().Y + Random.Shared.Next(-20, 20)
                        ));
                    }

                    ctx.DrawBeziers(
                        new SolidPen(color, thickness),
                        points.ToArray()
                    );
                }
            });
        }

        private void DistortText(Image<Rgba32> image)
        {
            // 添加轻微高斯模糊
            image.Mutate(ctx => ctx.GaussianBlur(0.8f));
        }
    }
}
